﻿using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Text;

namespace MedicalSoft.Application.HIS.Util.CryptoUtil
{
    public class SM4Utils
    {
        public string secretKey = "";
        public string iv = "";
        public bool hexString = false;

        public string Encrypt_ECB(string plainText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));

            string cipherText = Encoding.UTF8.GetString(Hex.Encode(encrypted));
            return cipherText;
        }

        public byte[] Encrypt_ECB_To_Byte(string plainText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Encoding.UTF8.GetBytes(plainText));
            return encrypted;
        }

        public string Decrypt_ECB_Byte(byte[] cipherText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, cipherText);
            return Encoding.UTF8.GetString(decrypted);
        }

        public string Decrypt_ECB(string cipherText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
            }
            else
            {
                keyBytes = Encoding.UTF8.GetBytes(secretKey);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Hex.Decode(cipherText));
            return Encoding.UTF8.GetString(decrypted);
        }
        public string Encrypt_CBC(string plainText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.Default.GetBytes(secretKey);
                ivBytes = Encoding.Default.GetBytes(iv);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Encoding.Default.GetBytes(plainText));

            string cipherText = Encoding.Default.GetString(Hex.Encode(encrypted));
            return cipherText;
        }

        public string Decrypt_CBC(string cipherText)
        {
            SM4_Context ctx = new SM4_Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString)
            {
                keyBytes = Hex.Decode(secretKey);
                ivBytes = Hex.Decode(iv);
            }
            else
            {
                keyBytes = Encoding.Default.GetBytes(secretKey);
                ivBytes = Encoding.Default.GetBytes(iv);
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, Hex.Decode(cipherText));
            return Encoding.Default.GetString(decrypted);
        }

        public static string Encrypt(string input, string appSecret)
        {
            var password = StringToHexString(appSecret).Substring(0, 32);
            SM4Utils sm4 = new SM4Utils();
            sm4.secretKey = password;
            sm4.hexString = true;
            string cipherText = sm4.Encrypt_ECB(input);
            return cipherText.ToUpper();
        }

        public static byte[] EncryptNormal(string input, string appSecret)
        {
            var password = StringToHexString(appSecret).Substring(0, 32);
            SM4Utils sm4 = new SM4Utils();
            sm4.secretKey = password;
            sm4.hexString = true;
            byte[] cipherText = sm4.Encrypt_ECB_To_Byte(input);
            return cipherText;
        }



        public static string EncryptToString(string input, string appSecret)
        {
            var password = StringToHexString(appSecret).Substring(0, 32);
            SM4Utils sm4 = new SM4Utils();
            sm4.secretKey = password;
            sm4.hexString = true;
            string cipherText = sm4.Encrypt_ECB(input);            
            return cipherText;
        }

        public static string DecryptNormal(byte[] input, string appSecret)
        {
            var password = StringToHexString(appSecret).Substring(0, 32);
            SM4Utils sm4 = new SM4Utils();
            sm4.secretKey = password;
            sm4.hexString = true;

            string cipherText = sm4.Decrypt_ECB_Byte(input);
            return cipherText;
        }


        public static string Decrypt(string input, string appSecret)
        {
            var password = StringToHexString(appSecret).Substring(0, 32);
            SM4Utils sm4 = new SM4Utils();
            sm4.secretKey = password;
            sm4.hexString = true;

            string cipherText = sm4.Decrypt_ECB(input);
            return cipherText;
        }

        public static string StringToHexString(string s)
        {
            Encoding encode = Encoding.UTF8;
            byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组
            string result = string.Empty;
            for (int i = 0; i < b.Length; i++)
            {
                result += Convert.ToString(b[i], 16);//逐字节变为16进制字符
            }
            return result;
        }


    }
}